﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CodeFarmer.Core.Web
{
    using System;
    using System.Collections;
    using System.Threading;
    using System.Web;
    using System.Web.Caching;
    namespace net91com.Core.Web
    {
        /// <summary>
        /// CacheHelper Web缓存帮助类 添加,移除,读取缓存
        /// </summary>
        public class CacheHelper
        {
            /// <summary>
            /// 缓存数据源更新委托
            /// </summary>
            /// <returns></returns>
            public delegate object RefreshCacheDataHandler();
            /// <summary>
            /// 带ref int的缓存数据源更新委托，一般用于分页方法
            /// </summary>
            /// <param name="recordCount"></param>
            /// <returns></returns>
            public delegate object RefreshCacheDataWithRefParamHandler(ref int recordCount);
            /// <summary>
            /// 带out int的缓存数据源更新委托，一般用于分页方法
            /// </summary>
            /// <param name="recordCount"></param>
            /// <returns></returns>
            public delegate object RefreshCacheDataWithOutParamHandler(out int recordCount);
            /// <summary>
            /// 通过缓存键获取相应的内容
            /// </summary>
            /// <typeparam name="T">类型</typeparam>
            /// <param name="key">缓存键</param>
            /// <returns></returns>
            public static T Get<T>(string key)
            {
                return (T)HttpRuntime.Cache[key];
            }
            /// <summary>
            /// 试着取得缓存内容，如果有返回真，并返回取得后的值。没有则返回默认值。
            /// </summary>
            /// <typeparam name="T">类型</typeparam>
            /// <param name="key">缓存键</param>
            /// <param name="outValue">返回相应类型的值</param>
            /// <returns></returns>
            public static bool TryGetValue<T>(string key, out T outValue)
            {
                if (HttpRuntime.Cache[key] != null)
                {
                    try
                    {
                        outValue = (T)HttpRuntime.Cache[key];
                        bool result = true;
                        return result;
                    }
                    catch
                    {
                        outValue = default(T);
                        bool result = false;
                        return result;
                    }
                }
                outValue = default(T);
                return false;
            }
            /// <summary>
            /// 判断是否有此key的值
            /// </summary>
            /// <param name="key"></param>
            /// <returns></returns>
            public static bool Contains(string key)
            {
                return HttpRuntime.Cache[key] != null;
            }
            /// <summary>
            /// 新增，添加缓存
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="key"></param>
            /// <param name="value"></param>
            /// <param name="lNumofMilliSeconds"></param>
            public static void Set<T>(string key, T value, long lNumofMilliSeconds)
            {
                HttpRuntime.Cache.Add(key, value, null, DateTime.Now.AddMilliseconds((double)lNumofMilliSeconds), TimeSpan.Zero, CacheItemPriority.NotRemovable, null);
            }
            /// <summary>
            /// 新增，添加缓存
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="key"></param>
            /// <param name="value"></param>
            /// <param name="tspan"></param>
            public static void Set<T>(string key, T value, TimeSpan tspan)
            {
                HttpRuntime.Cache.Add(key, value, null, DateTime.Now.Add(tspan), TimeSpan.Zero, CacheItemPriority.NotRemovable, null);
            }
            /// <summary>
            /// 清除所有缓存
            /// </summary>
            public static void Clear()
            {
                foreach (DictionaryEntry elem in HttpRuntime.Cache)
                {
                    HttpRuntime.Cache.Remove(elem.Key.ToString());
                }
            }
            /// <summary>
            /// 移除相关关键字的缓存
            /// </summary>
            /// <param name="keyword">缓存关键字</param>
            public static void Remove(string keyword)
            {
                foreach (DictionaryEntry elem in HttpRuntime.Cache)
                {
                    if (elem.Key.ToString().Contains(keyword))
                    {
                        HttpRuntime.Cache.Remove(elem.Key.ToString());
                    }
                }
            }
            /// <summary>
            /// 清除某项缓存
            /// </summary>
            /// <param name="key">缓存键</param>
            public static void RemoveAt(string key)
            {
                if (HttpRuntime.Cache[key] != null)
                {
                    HttpRuntime.Cache.Remove(key);
                }
            }
            /// <summary>
            /// 获取绝对日期时间
            /// </summary>
            /// <param name="CacheTimeOption">缓存的时间长短</param>
            /// <param name="CacheExpirationOption"></param>
            /// <returns></returns>
            public static DateTime GetAbsoluteExpirationTime(CacheTimeOption CacheTimeOption, CacheExpirationOption CacheExpirationOption)
            {
                if (CacheExpirationOption == CacheExpirationOption.SlidingExpiration || CacheTimeOption == CacheTimeOption.NotRemovable)
                {
                    return Cache.NoAbsoluteExpiration;
                }
                return DateTime.Now.AddMinutes((double)CacheTimeOption);
            }
            /// <summary>
            /// 获取弹性时间过期时间
            /// </summary>
            /// <param name="CacheTimeOption">缓存的时间长短</param>
            /// <param name="CacheExpirationOption"></param>
            /// <returns></returns>
            private static TimeSpan GetSlidingExpirationTime(CacheTimeOption CacheTimeOption, CacheExpirationOption CacheExpirationOption)
            {
                if (CacheExpirationOption == CacheExpirationOption.AbsoluteExpiration || CacheTimeOption == CacheTimeOption.NotRemovable)
                {
                    return Cache.NoSlidingExpiration;
                }
                return TimeSpan.FromMinutes((double)CacheTimeOption);
            }
            /// <summary>
            /// 添加缓存
            /// </summary>
            /// <typeparam name="T">类型</typeparam>
            /// <param name="key">缓存键</param>
            /// <param name="value">值</param>
            /// <param name="CacheTimeOption">缓存的时间长短</param>
            /// <param name="CacheExpirationOption"></param>
            /// <param name="dependencies">缓存依赖项</param>
            /// <param name="cacheItemPriority">优先级</param>
            /// <param name="callback">回调函数</param>
            public static void Set<T>(string key, T value, CacheTimeOption CacheTimeOption, CacheExpirationOption CacheExpirationOption, CacheDependency dependencies, CacheItemPriority cacheItemPriority, CacheItemRemovedCallback callback)
            {
                if (value != null && CacheTimeOption != CacheTimeOption.None)
                {
                    DateTime absoluteExpiration = CacheHelper.GetAbsoluteExpirationTime(CacheTimeOption, CacheExpirationOption);
                    TimeSpan slidingExpiration = CacheHelper.GetSlidingExpirationTime(CacheTimeOption, CacheExpirationOption);
                    HttpRuntime.Cache.Add(key, value, dependencies, absoluteExpiration, slidingExpiration, cacheItemPriority, callback);
                }
            }
            /// <summary>
            /// 添加缓存
            /// </summary>
            /// <typeparam name="T">类型</typeparam>
            /// <param name="key">缓存键</param>
            /// <param name="value">值</param>
            /// <param name="CacheTimeOption">缓存的时间长短</param>
            /// <param name="CacheExpirationOption"></param>
            /// <param name="dependencies">缓存依赖项</param>
            /// <param name="cacheItemPriority">优先级</param>
            public static void Set<T>(string key, T value, CacheTimeOption CacheTimeOption, CacheExpirationOption CacheExpirationOption, CacheDependency dependencies, CacheItemPriority cacheItemPriority)
            {
                CacheHelper.Set<T>(key, value, CacheTimeOption, CacheExpirationOption, dependencies, cacheItemPriority, null);
            }
            /// <summary>
            /// 添加缓存
            /// </summary>
            /// <typeparam name="T">类型</typeparam>
            /// <param name="key">缓存键</param>
            /// <param name="value">值</param>
            /// <param name="CacheTimeOption">缓存时间</param>
            /// <param name="CacheExpirationOption">缓存过期时间类别（绝对/弹性）</param>
            /// <param name="dependencies">缓存依赖项</param>
            public static void Set<T>(string key, T value, CacheTimeOption CacheTimeOption, CacheExpirationOption CacheExpirationOption, CacheDependency dependencies)
            {
                CacheHelper.Set<T>(key, value, CacheTimeOption, CacheExpirationOption, dependencies, CacheItemPriority.NotRemovable, null);
            }
            /// <summary>
            /// 添加缓存
            /// </summary>
            /// <typeparam name="T">类型</typeparam>
            /// <param name="key">缓存键</param>
            /// <param name="value">值</param>
            /// <param name="CacheTimeOption">缓存时间</param>
            /// <param name="CacheExpirationOption">缓存过期时间类别（绝对/弹性）</param>
            public static void Set<T>(string key, T value, CacheTimeOption CacheTimeOption, CacheExpirationOption CacheExpirationOption)
            {
                CacheHelper.Set<T>(key, value, CacheTimeOption, CacheExpirationOption, null, CacheItemPriority.NotRemovable, null);
            }
            /// <summary>
            /// 添加缓存
            /// </summary>
            /// <typeparam name="T">类型</typeparam>
            /// <param name="key">缓存键</param>
            /// <param name="value">值</param>
            /// <param name="callback">回调函数</param>
            /// <param name="CacheTimeOption">缓存时间</param>
            public static void Set<T>(string key, T value, CacheTimeOption CacheTimeOption, CacheItemRemovedCallback callback)
            {
                CacheHelper.Set<T>(key, value, CacheTimeOption, CacheExpirationOption.AbsoluteExpiration, null, CacheItemPriority.NotRemovable, callback);
            }
            /// <summary>
            /// 添加缓存
            /// </summary>
            /// <typeparam name="T">类型</typeparam>
            /// <param name="key">缓存键</param>
            /// <param name="value">值</param>
            /// <param name="CacheTimeOption">缓存时间</param>
            public static void Set<T>(string key, T value, CacheTimeOption CacheTimeOption)
            {
                CacheHelper.Set<T>(key, value, CacheTimeOption, CacheExpirationOption.AbsoluteExpiration, null, CacheItemPriority.NotRemovable, null);
            }
            /// <summary>
            /// 添加缓存
            /// </summary>
            /// <typeparam name="T">类型</typeparam>
            /// <param name="key">缓存键</param>
            /// <param name="value">值</param>
            public static void Set<T>(string key, T value)
            {
                CacheHelper.Set<T>(key, value, CacheTimeOption.Normal, CacheExpirationOption.AbsoluteExpiration, null, CacheItemPriority.NotRemovable, null);
            }
            /// <summary>
            /// 获取指定key缓存数据，如果该缓存不存在，则自动调用数据源委托生成缓存
            /// </summary>
            /// <typeparam name="T">缓存数据的类型</typeparam>
            /// <param name="key">缓存key</param>
            /// <param name="cacheTime">缓存时间</param>
            /// <param name="callback">数据源委托</param>
            /// <param name="removedCallback">缓存失效时的回调函数</param>
            /// <returns></returns>
            public static T Get<T>(string key, CacheTimeOption cacheTime, CacheHelper.RefreshCacheDataHandler callback, CacheItemRemovedCallback removedCallback) where T : class
            {
                if (cacheTime == CacheTimeOption.None)
                {
                    return callback() as T;
                }
                if (CacheHelper.Contains(key))
                {
                    return CacheHelper.Get<T>(key);
                }
                T content = callback() as T;
                CacheHelper.Set<T>(key, content, cacheTime, removedCallback);
                return content;
            }
            /// <summary>
            /// 获取指定key缓存数据，如果该缓存不存在，则自动调用数据源委托生成缓存
            /// </summary>
            /// <typeparam name="T">缓存数据的类型</typeparam>
            /// <param name="key">缓存key</param>
            /// <param name="cacheTime">缓存时间</param>
            /// <param name="callback">数据源委托</param>
            /// <returns></returns>
            public static T Get<T>(string key, CacheTimeOption cacheTime, CacheHelper.RefreshCacheDataHandler callback) where T : class
            {
                if (cacheTime == CacheTimeOption.None)
                {
                    return callback() as T;
                }
                if (CacheHelper.Contains(key))
                {
                    return CacheHelper.Get<T>(key);
                }
                T content = callback() as T;
                CacheHelper.Set<T>(key, content, cacheTime);
                return content;
            }
            /// <summary>
            /// 获取指定key缓存数据，如果该缓存不存在，则自动调用数据源委托生成缓存
            /// </summary>
            /// <typeparam name="T">缓存数据的类型</typeparam>
            /// <param name="key">缓存key</param>
            /// <param name="recordCountKey">记录总数的缓存key</param>
            /// <param name="recordCount">记录总数(ref)</param>
            /// <param name="cacheTime">缓存时间</param>
            /// <param name="callback">数据源委托</param>
            /// <returns></returns>
            public static T Get<T>(string key, string recordCountKey, ref int recordCount, CacheTimeOption cacheTime, CacheHelper.RefreshCacheDataWithRefParamHandler callback) where T : class
            {
                if (cacheTime == CacheTimeOption.None)
                {
                    return callback(ref recordCount) as T;
                }
                if (CacheHelper.Contains(recordCountKey))
                {
                    recordCount = CacheHelper.Get<int>(recordCountKey);
                }
                if (CacheHelper.Contains(key) && recordCount != 0)
                {
                    return CacheHelper.Get<T>(key);
                }
                T content = callback(ref recordCount) as T;
                CacheHelper.Set<T>(key, content, cacheTime);
                CacheHelper.Set<int>(recordCountKey, recordCount, cacheTime);
                return content;
            }
            /// <summary>
            /// 获取指定key缓存数据，如果该缓存不存在，则自动调用数据源委托生成缓存
            /// </summary>
            /// <typeparam name="T">缓存数据的类型</typeparam>
            /// <param name="key">缓存key</param>
            /// <param name="recordCountKey">记录总数的缓存key</param>
            /// <param name="recordCount">记录总数(out)</param>
            /// <param name="cacheTime">缓存时间</param>
            /// <param name="callback">数据源委托</param>
            /// <returns></returns>
            public static T Get<T>(string key, string recordCountKey, out int recordCount, CacheTimeOption cacheTime, CacheHelper.RefreshCacheDataWithOutParamHandler callback) where T : class
            {
                if (cacheTime == CacheTimeOption.None)
                {
                    return callback(out recordCount) as T;
                }
                recordCount = 0;
                if (CacheHelper.Contains(recordCountKey))
                {
                    recordCount = CacheHelper.Get<int>(recordCountKey);
                }
                if (CacheHelper.Contains(key) && recordCount != 0)
                {
                    return CacheHelper.Get<T>(key);
                }
                T content = callback(out recordCount) as T;
                CacheHelper.Set<T>(key, content, cacheTime);
                CacheHelper.Set<int>(recordCountKey, recordCount, cacheTime);
                return content;
            }
            /// <summary>
            /// 获取指定key缓存数据，如果该缓存不存在，则自动调用数据源委托生成缓存(线程安全，但会造成一定性能开销)
            /// </summary>
            /// <typeparam name="T">缓存数据的类型</typeparam>
            /// <param name="key">缓存key</param>
            /// <param name="cacheTime">缓存时间</param>
            /// <param name="callback">数据源委托</param>
            /// <returns></returns>
            public static T GetWithLock<T>(string key, CacheTimeOption cacheTime, CacheHelper.RefreshCacheDataHandler callback) where T : class
            {
                if (cacheTime == CacheTimeOption.None)
                {
                    return callback() as T;
                }
                if (CacheHelper.Contains(key))
                {
                    return CacheHelper.Get<T>(key);
                }
                string obj;
                Monitor.Enter(obj = string.Intern(key));
                T result;
                try
                {
                    if (CacheHelper.Contains(key))
                    {
                        result = CacheHelper.Get<T>(key);
                    }
                    else
                    {
                        T content = callback() as T;
                        CacheHelper.Set<T>(key, content, cacheTime);
                        result = content;
                    }
                }
                finally
                {
                    Monitor.Exit(obj);
                }
                return result;
            }
            /// <summary>
            /// 获取指定key缓存数据，如果该缓存不存在，则自动调用数据源委托生成缓存(线程安全，但会造成一定性能开销)
            /// </summary>
            /// <typeparam name="T">缓存数据的类型</typeparam>
            /// <param name="key">缓存key</param>
            /// <param name="recordCountKey">记录总数的缓存key</param>
            /// <param name="recordCount">记录总数(ref)</param>
            /// <param name="cacheTime">缓存时间</param>
            /// <param name="callback">数据源委托</param>
            /// <returns></returns>
            public static T GetWithLock<T>(string key, string recordCountKey, ref int recordCount, CacheTimeOption cacheTime, CacheHelper.RefreshCacheDataWithRefParamHandler callback) where T : class
            {
                if (cacheTime == CacheTimeOption.None)
                {
                    return callback(ref recordCount) as T;
                }
                if (CacheHelper.Contains(recordCountKey))
                {
                    recordCount = CacheHelper.Get<int>(recordCountKey);
                }
                if (CacheHelper.Contains(key))
                {
                    return CacheHelper.Get<T>(key);
                }
                string obj;
                Monitor.Enter(obj = string.Intern(key));
                T result;
                try
                {
                    if (CacheHelper.Contains(recordCountKey))
                    {
                        recordCount = CacheHelper.Get<int>(recordCountKey);
                    }
                    if (CacheHelper.Contains(key))
                    {
                        result = CacheHelper.Get<T>(key);
                    }
                    else
                    {
                        T content = callback(ref recordCount) as T;
                        CacheHelper.Set<T>(key, content, cacheTime);
                        CacheHelper.Set<int>(recordCountKey, recordCount, cacheTime);
                        result = content;
                    }
                }
                finally
                {
                    Monitor.Exit(obj);
                }
                return result;
            }
            /// <summary>
            /// 获取指定key缓存数据，如果该缓存不存在，则自动调用数据源委托生成缓存(线程安全，但会造成一定性能开销)
            /// </summary>
            /// <typeparam name="T">缓存数据的类型</typeparam>
            /// <param name="key">缓存key</param>
            /// <param name="recordCountKey">记录总数的缓存key</param>
            /// <param name="recordCount">记录总数(out)</param>
            /// <param name="cacheTime">缓存时间</param>
            /// <param name="callback">数据源委托</param>
            /// <returns></returns>
            public static T GetWithLock<T>(string key, string recordCountKey, out int recordCount, CacheTimeOption cacheTime, CacheHelper.RefreshCacheDataWithOutParamHandler callback) where T : class
            {
                if (cacheTime == CacheTimeOption.None)
                {
                    return callback(out recordCount) as T;
                }
                recordCount = 0;
                if (CacheHelper.Contains(recordCountKey))
                {
                    recordCount = CacheHelper.Get<int>(recordCountKey);
                }
                if (CacheHelper.Contains(key))
                {
                    return CacheHelper.Get<T>(key);
                }
                string obj;
                Monitor.Enter(obj = string.Intern(key));
                T result;
                try
                {
                    if (CacheHelper.Contains(recordCountKey))
                    {
                        recordCount = CacheHelper.Get<int>(recordCountKey);
                    }
                    if (CacheHelper.Contains(key))
                    {
                        result = CacheHelper.Get<T>(key);
                    }
                    else
                    {
                        T content = callback(out recordCount) as T;
                        CacheHelper.Set<T>(key, content, cacheTime);
                        CacheHelper.Set<int>(recordCountKey, recordCount, cacheTime);
                        result = content;
                    }
                }
                finally
                {
                    Monitor.Exit(obj);
                }
                return result;
            }
        }
    }

}
